home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d2 / sysid47.arc / SYSID.INC < prev    next >
Text File  |  1989-12-17  |  60KB  |  2,641 lines

  1. (*
  2. **    SYSID.INC
  3. **
  4. **    Version 4.7
  5. **
  6. **    The functions and procedures for SYSID.PAS
  7. **
  8. **    Steve Grant
  9. **    Long Beach, CA
  10. **    July 31, 1989
  11. *)
  12.  
  13. procedure caption1(a : string);
  14.  
  15. begin
  16.     textcolor(lightgray);
  17.     write(a);
  18.     textcolor(lightgreen)
  19. end;
  20.  
  21. procedure caption2(a : string);
  22.  
  23. const
  24.     capterm = ': ';
  25.  
  26. var
  27.     i : byte;
  28.  
  29. begin
  30.     i := length(a);
  31.     while (i > 0) and (a[i] = ' ') do
  32.         dec(i);
  33.     insert(capterm, a, i + 1);
  34.     caption1(a)
  35. end;
  36.  
  37. function nocarry : boolean;
  38.  
  39. begin
  40.     nocarry := regs.flags and fcarry = $0000
  41. end;
  42.  
  43. function hex(a : word; b : byte) : string;
  44.  
  45. const
  46.     digit : array[$0..$F] of char = '0123456789ABCDEF';
  47.  
  48. var
  49.     i : byte;
  50.     xstring : string;
  51.  
  52. begin
  53.     xstring := '';
  54.     for i := 1 to b do begin
  55.         insert(digit[a and $000F], xstring, 1);
  56.         a := a shr 4
  57.     end;
  58.     hex := xstring
  59. end;
  60.  
  61. procedure unknown(a : string; b : word; c : byte);
  62.  
  63. begin
  64.     writeln('(unknown', ' ', a, ' ', hex(b, c), ')')
  65. end;
  66.  
  67. procedure caption3(a : string);
  68.  
  69. begin
  70.     caption2('  ' + a)
  71. end;
  72.  
  73. procedure yesorno1(a : boolean);
  74.  
  75. begin
  76.     if a then
  77.         write('yes')
  78.     else
  79.         write('no ')
  80. end;
  81.  
  82. procedure yesorno2(a : boolean);
  83.  
  84. begin
  85.     yesorno1(a);
  86.     writeln
  87. end;
  88.  
  89. procedure dontknow1;
  90.  
  91. begin
  92.     write('(unknown)')
  93. end;
  94.  
  95. procedure dontknow2;
  96.  
  97. begin
  98.     dontknow1;
  99.     writeln
  100. end;
  101.  
  102. procedure pause1;
  103.  
  104. var
  105.     xbyte : byte;
  106.     xchar : char;
  107.  
  108. begin
  109.     if wherey + hi(windmin) > hi(windmax) then begin
  110.         xbyte := textattr;
  111.         textcolor(green);
  112.         write('(continued)');
  113.         repeat
  114.             xchar := readkey
  115.         until not keypressed;
  116.         clrscr;
  117.         writeln('(continued)');
  118.         textattr := xbyte
  119.     end
  120. end;
  121.  
  122. procedure CPUID(var a : cpu_info_t);
  123.  
  124. external;
  125.  
  126. procedure segofs1(a, b : word);
  127.  
  128. begin
  129.     write(hex(a, 4), ':', hex(b, 4))
  130. end;
  131.  
  132. procedure segofs2(a, b : word);
  133.  
  134. begin
  135.     segofs1(a, b);
  136.     writeln
  137. end;
  138.  
  139. function showchar(a : char) : char;
  140.  
  141. begin
  142.     if a in pchar then
  143.         showchar := a
  144.     else
  145.         showchar := '.'
  146. end;
  147.  
  148. function bin4(a : byte) : string;
  149.  
  150. const
  151.     digit : array[0..1] of char = '01';
  152.  
  153. var
  154.     xstring : string;
  155.     i : byte;
  156.  
  157. begin
  158.     xstring := '';
  159.     for i := 3 downto 0 do begin
  160.         insert(digit[a mod 2], xstring, 1);
  161.         a := a shr 1
  162.     end;
  163.     bin4 := xstring
  164. end;
  165.  
  166. procedure offoron(a : boolean);
  167.  
  168. begin
  169.     if a then
  170.         write('on')
  171.     else
  172.         write('off')
  173. end;
  174.  
  175. procedure zeropad(a : word);
  176.  
  177. begin
  178.     if a < 10 then
  179.         write('0');
  180.     write(a)
  181. end;
  182.  
  183. function cbw(a, b : byte) : word;
  184.  
  185. begin
  186.     cbw := b shl 8 + a
  187. end;
  188.  
  189. function bin16(a : word) : string;
  190.  
  191. function bin8(a : byte) : string;
  192.  
  193. begin
  194.     bin8 := bin4(a shr 4) + '_' + bin4(a and $0F)
  195. end;
  196.  
  197. begin (* function bin16 *)
  198.     bin16 := bin8(hi(a)) + '_' + bin8(lo(a))
  199. end;
  200.  
  201. procedure drvname(a : byte);
  202.  
  203. begin
  204.     write(chr(ord('A') + a), ': ')
  205. end;
  206.  
  207. procedure media(a : byte);
  208.  
  209. procedure diskette(a, b : byte);
  210.  
  211. begin
  212.     writeln('diskette (', a, '-sided, ', b, ' sectors)')
  213. end;
  214.  
  215. begin (* procedure media *)
  216.     caption3('Media');
  217.     case a of
  218.         $FF : diskette(2, 8);
  219.         $FE : diskette(1, 8);
  220.         $FD : diskette(2, 9);
  221.         $FC : diskette(1, 9);
  222.         $F9 : diskette(2, 15);
  223.         $F8 : writeln('fixed disk')
  224.         else
  225.             unknown('media', a, 2)
  226.     end
  227. end;
  228.  
  229. procedure pause2;
  230.  
  231. var
  232.     xbyte : byte;
  233.     xchar : char;
  234.  
  235. begin
  236.     xbyte := textattr;
  237.     textcolor(green);
  238.     write('(continued)');
  239.     repeat
  240.         xchar := readkey
  241.     until not keypressed;
  242.     textattr := xbyte
  243. end;
  244.  
  245. function diskread(drive : byte; starting_sector, number_of_sectors : word
  246.     ; var buffer) : word;
  247.  
  248. external;
  249.  
  250. (****************************************************************************)
  251.  
  252. procedure init;
  253.  
  254. const
  255.     qversion = 'Version 4.7';
  256.  
  257. var
  258.     xint : integer;
  259.  
  260. procedure rjustify(a : string);
  261.  
  262. begin
  263.     gotoxy(1 + lo(windmax) - length(a), wherey);
  264.     write(a)
  265. end;
  266.  
  267. procedure border;
  268.  
  269. const
  270.     ch = '═';
  271.  
  272. var
  273.     i : byte;
  274.  
  275. begin
  276.     for i := 1 to twidth - 1 do
  277.         write(ch)
  278. end;
  279.  
  280. begin (* procedure init *)
  281.     attrsave := textattr;
  282.     with regs do begin
  283.         AH := $0F;
  284.         intr($10, regs);
  285.         twidth := AH;
  286.         vidpg := BH;
  287.         intr($11, regs);
  288.         equip := AX;
  289.         intr($12, regs);
  290.         DOSmem := longint(AX) shl 10;
  291.         AH := $19;
  292.         MSDOS(regs);
  293.         currdrv := AL;
  294.         AH := $34;
  295.         MSDOS(regs);
  296.         DOScseg := ES;
  297.         DOScofs := BX;
  298.         AX := $3700;
  299.         MSDOS(regs);
  300.         switchar := chr(DL);
  301.         AX := $3800;
  302.         DS := seg(country);
  303.         DX := ofs(country);
  304.         MSDOS(regs);
  305.         ccode := BX;
  306.         AH := $52;
  307.         MSDOS(regs);
  308.         devseg := ES;
  309.         devofs := BX
  310.     end;
  311.     detectgraph(graphdriver, xint);
  312.     if (graphdriver = EGA) or (graphdriver = MCGA)
  313.         or (graphdriver = VGA) then
  314.         with regs do begin
  315.             AX := $1130;
  316.             BH := $00;
  317.             intr($10, regs);
  318.             tlength := DL + 1
  319.         end
  320.     else
  321.         tlength := 25;
  322.     for i := $00 to $FF do
  323.         getintvec(i, intvec[i]);
  324.     intvec[$00] := saveint00;
  325.     intvec[$02] := saveint02;
  326.     intvec[$1B] := saveint1B;
  327.     intvec[$23] := saveint23;
  328.     intvec[$24] := saveint24;
  329.     intvec[$34] := saveint34;
  330.     intvec[$35] := saveint35;
  331.     intvec[$36] := saveint36;
  332.     intvec[$37] := saveint37;
  333.     intvec[$38] := saveint38;
  334.     intvec[$39] := saveint39;
  335.     intvec[$3A] := saveint3A;
  336.     intvec[$3B] := saveint3B;
  337.     intvec[$3C] := saveint3C;
  338.     intvec[$3D] := saveint3D;
  339.     intvec[$3E] := saveint3E;
  340.     intvec[$3F] := saveint3F;
  341.     intvec[$75] := saveint75;
  342.     dirsep := ['\'];
  343.     if switchar <> '/' then
  344.         dirsep := dirsep + ['/'];
  345.     textbackground(black);
  346.     window(1, 1, twidth, tlength);
  347.     clrscr;
  348.     textcolor(green);
  349.     write('SYSID');
  350.     textcolor(lightgray);
  351.     write(' - System description for IBM PC''s and compatibles');
  352.     rjustify(qversion);
  353.     writeln;
  354.     border;
  355.     gotoxy(1, tlength - 1);
  356.     border;
  357.     writeln;
  358.     write('Page ');
  359.     x1 := wherex + lo(windmin);
  360.     write(pgmax, ' of ', pgmax);
  361.     textcolor(green);
  362.     rjustify('PgDn PgUp Home End Esc');
  363.     x2 := wherex + lo(windmin);
  364.     pg := 1
  365. end;
  366.  
  367. (****************************************************************************)
  368.  
  369. procedure page_01;
  370.  
  371. const
  372.     BIOScseg = $C000;
  373.     BIOSext = $AA55;
  374.     PCROMseg = $F000;
  375.  
  376. var
  377.     xbool : boolean;
  378.     xbyte : byte;
  379.     xchar : char;
  380.     xlong : longint;
  381.     xword1 : word;
  382.     xword2 : word;
  383.  
  384. function BIOSscan(a, b, c : word; var d : word) : boolean;
  385.  
  386. const
  387.     max = 3;
  388.     notice : array[1..max] of string = ('(C)', 'COPR.', 'COPYRIGHT');
  389.  
  390. var
  391.     i : 1..max;
  392.     len : byte;
  393.     target : string;
  394.     xbool : boolean;
  395.     xlong : longint;
  396.     xword : word;
  397.  
  398. function scan(a : string; b, c, d : word; var e : word) : boolean;
  399.  
  400. var
  401.     i : longint;
  402.     j : byte;
  403.     len : byte;
  404.     xbool1 : boolean;
  405.     xbool2 : boolean;
  406.  
  407. begin
  408.     i := c;
  409.     len := length(a);
  410.     xbool1 := false;
  411.     repeat
  412.         if i <= longint(d) - len + 1 then begin
  413.             j := 0;
  414.             xbool2 := false;
  415.             repeat
  416.                 if j < len then
  417.                     if upcase(chr(mem[b : i + j])) = a[j + 1] then
  418.                         inc(j)
  419.                     else begin
  420.                         xbool2 := true;
  421.                         inc(i)
  422.                     end
  423.                 else begin
  424.                     xbool2 := true;
  425.                     xbool1 := true;
  426.                     e := i;
  427.                     scan := true
  428.                 end
  429.             until xbool2
  430.         end else begin
  431.             xbool1 := true;
  432.             scan := false
  433.         end
  434.     until xbool1
  435. end;
  436.  
  437. begin (* function BIOSscan *)
  438.     xlong := c;
  439.     xbool := false;
  440.     for i := 1 to max do begin
  441.         target := notice[i];
  442.         len := length(target);
  443.         if xbool then
  444.             xlong := longint(xword) - 2 + len;
  445.         if (xlong >= b) and (xlong <= c) and (scan(target, a, b, xlong, xword))
  446.             then
  447.             xbool := true
  448.     end;
  449.     if xbool then begin
  450.         while (xword > b) and (chr(mem[a : xword - 1]) in pchar) do
  451.             dec(xword);
  452.         d := xword
  453.     end;
  454.     BIOSscan := xbool
  455. end;
  456.  
  457. procedure showBIOS(a, b : word);
  458.  
  459. var
  460.     xchar : char;
  461.  
  462. begin
  463.     xchar := chr(mem[a : b]);
  464.     while (xchar in pchar) and (b > $0000) do begin
  465.         write(xchar);
  466.         inc(b);
  467.         xchar := chr(mem[a : b])
  468.     end;
  469.     writeln
  470. end;
  471.  
  472. begin (* procedure page_01 *)
  473.     caption2('Machine type');
  474.     with regs do begin
  475.         AH := $C0;
  476.         intr($15, regs);
  477.         if nocarry then begin
  478.             xword1 := memw[ES : BX + 2];
  479.             if (xword1 = $00FC) or (xword1 = $01FC) then
  480.                 writeln('PC-AT 3x9')
  481.             else if (xword1 = $00FB) or (xword1 = $01FB) then
  482.                 writeln('PC-XT/2')
  483.             else if xword1 = $02FC then
  484.                 writeln('PC-XT/286')
  485.             else if xword1 = $00F9 then
  486.                 writeln('PC-Convertible')
  487.             else if xword1 = $00FA then
  488.                 writeln('PS/2 Model 30')
  489.             else if xword1 = $04FC then
  490.                 writeln('PS/2 Model 50')
  491.             else if xword1 = $05FC then
  492.                 writeln('PS/2 Model 60')
  493.             else if (xword1 = $04F8) or (xword1 = $09F8) then
  494.                 writeln('PS/2 Model 70')
  495.             else if (xword1 = $00F8) or (xword1 = $01F8) then
  496.                 writeln('PS/2 Model 80')
  497.             else if xword1 = $06FC then
  498.                 writeln('7552 Gearbox')
  499.             else
  500.                 unknown('machine - model/type word', xword1, 4);
  501.             caption3('BIOS revision level');
  502.             writeln(mem[ES : BX + 4]);
  503.             xbyte := mem[ES : BX + 5];
  504.             caption3('DMA channel 3 used');
  505.             yesorno2(xbyte and $80 = $80);
  506.             caption3('Slave 8259 present');
  507.             yesorno2(xbyte and $40 = $40);
  508.             caption3('Real-time clock');
  509.             yesorno2(xbyte and $20 = $20);
  510.             caption3('Keyboard intercept available');
  511.             yesorno2(xbyte and $10 = $10);
  512.             caption3('Wait for external event available');
  513.             yesorno2(xbyte and $08 = $08);
  514.             caption3('Extended BIOS data area segment');
  515.             if xbyte and $04 = $04 then begin
  516.                 AH := $C1;
  517.                 intr($15, regs);
  518.                 if nocarry then
  519.                     writeln(hex(ES, 4))
  520.                 else
  521.                     dontknow2;
  522.             end else
  523.                 writeln('(none)');
  524.             caption3('Micro Channel');
  525.             yesorno2(xbyte and $02 = $02)
  526.         end else begin
  527.             xbyte := mem[$FFFF : $000E];
  528.             case xbyte of
  529.                 $FF : writeln('PC');
  530.                 $FE : writeln('PC-XT');
  531.                 $FD : writeln('PCjr');
  532.                 $FC : writeln('PC-AT')
  533.                 else
  534.                     unknown('machine - model byte', xbyte, 2)
  535.             end
  536.         end
  537.     end;
  538. (* Byte 12:12 p. 174 *)
  539.     caption2('BIOS source');
  540.     if BIOSscan(PCROMseg, $E000, $FFFF, xword1) then
  541.         showBIOS(PCROMseg, xword1)
  542.     else
  543.         dontknow2;
  544.     caption2('BIOS date');
  545.     i := $0005;
  546.     xbool := true;
  547.     xchar := chr(mem[$FFFF : i]);
  548.     while (i < $0010) and (xchar in pchar) do begin
  549.         xbool := false;
  550.         write(xchar);
  551.         inc(i);
  552.         xchar := chr(mem[$FFFF : i])
  553.     end;
  554.     if xbool then
  555.         dontknow1;
  556.     writeln;
  557.     caption2('BIOS extensions');
  558.     xword1 := BIOScseg;
  559.     xbool := true;
  560.     for i := 0 to 23 do begin
  561.         if (memw[xword1 : 0] = BIOSext) then begin
  562.             if xbool then begin
  563.                 writeln;
  564.                 window(3, wherey + hi(windmin), twidth, tlength - 2);
  565.                 caption1('Segment   Copyright notice');
  566.                 writeln;
  567.                 xbool := false
  568.             end;
  569.             pause1;
  570.             write(hex(xword1, 4), '      ');
  571.             if BIOSscan(xword1, $0000, $1FFF, xword2) then
  572.                 showBIOS(xword1, xword2)
  573.             else
  574.                 dontknow2
  575.         end;
  576.         inc(xword1, $0200)
  577.     end;
  578.     if xbool then
  579.         writeln('(none)')
  580. end;
  581.  
  582. (****************************************************************************)
  583.  
  584. procedure page_02;
  585.  
  586. var
  587.     cpu_info : cpu_info_t;
  588.  
  589. procedure showNDP(a : string; b : word);
  590.  
  591. begin
  592.     writeln(a);
  593.     caption2('  Infinity');
  594.     case b and $1000 of
  595.         $0000 : writeln('projective');
  596.         $1000 : writeln('affine')
  597.     end;
  598.     caption2('  Rounding');
  599.     case b and $0C00 of
  600.         $0000 : writeln('to nearest or even');
  601.         $0400 : writeln('down');
  602.         $0800 : writeln('up');
  603.         $0C00 : writeln('chop')
  604.     end;
  605.     caption2('  Precision');
  606.     case b and $0300 of
  607.         $0000 : writeln('24 bits');
  608.         $0100 : writeln('(reserved)');
  609.         $0200 : writeln('53 bits');
  610.         $0300 : writeln('64 bits')
  611.     end
  612. end;
  613.  
  614. begin (* procedure page_02 *)
  615.     caption2('CPU');
  616.     CPUID(cpu_info);
  617.     with cpu_info do begin
  618.         case cpu_type of
  619.             $00 : writeln('8088');
  620.             $01 : writeln('8086');
  621.             $02 : writeln('V20');
  622.             $03 : writeln('V30');
  623.             $04 : writeln('80188');
  624.             $05 : writeln('80186');
  625.             $06 : writeln('80286');
  626.             $07 : writeln('80386')
  627.             else
  628.                 unknown('CPU', cpu_type, 2)
  629.         end;
  630.         case cpu_type of
  631.             $06..$07 : begin
  632.                 caption3('Machine State Word');
  633.                 writeln(hex(MSW, 4));
  634.                 caption3('Global Descriptor Table   ');
  635.                 for i := 1 to 6 do
  636.                     write(hex(GDT[i], 2), ' ');
  637.                 writeln;
  638.                 caption3('Interrupt Descriptor Table');
  639.                 for i := 1 to 6 do
  640.                     write(hex(IDT[i], 2), ' ');
  641.                 writeln
  642.             end
  643.         end;
  644.         case cpu_type of
  645.             07 : begin
  646.                 caption3('Operand size (bits)');
  647.                 if opsize then
  648.                     writeln('32')
  649.                 else
  650.                     writeln('16')
  651.             end
  652.         end;
  653.         caption3('Interrupts enabled correctly after segment register'
  654.             + ' change');
  655.         yesorno2(chkint);
  656.         case cpu_type of
  657.             07 : begin
  658.                 caption3('Multiplication correct');
  659.                 yesorno2(mult)
  660.             end
  661.         end;
  662.         caption2('Coprocessor');
  663.         case ndp_type of
  664.             $00 : writeln('none');
  665.             $01 : showNDP('8087', ndp_cw);
  666.             $02 : showNDP('80287', ndp_cw);
  667.             $03 : showNDP('80387', ndp_cw)
  668.             else
  669.                 dontknow2
  670.         end
  671.     end;
  672.     caption2('Coprocessor enabled');
  673.     yesorno2(equip and $0002 = $0002)
  674. end;
  675.  
  676. (****************************************************************************)
  677.  
  678. procedure page_03;
  679.  
  680. const
  681.     EMMint = $67;
  682.     qEMMdrvr = 'EMMXXXX0';
  683.  
  684. var
  685.     EMMarray : array[$000..$3FF] of word;
  686.     xlong : longint;
  687.     xword1 : word;
  688.     xword2 : word;
  689.     xstring : string;
  690.  
  691. procedure EMMerr(a : byte);
  692.  
  693. begin
  694.     case a of
  695.         $80 : writeln('internal error in EMM software');
  696.         $81 : writeln('malfunction in expanded memory hardware');
  697.         $82 : writeln('memory manager busy');
  698.         $83 : writeln('invalid handle');
  699.         $84 : writeln('undefined function');
  700.         $85 : writeln('no more handles available');
  701.         $86 : writeln('error in save or restore of mapping context');
  702.         $87 : writeln('not enough physical pages available');
  703.         $88 : writeln('not enough free pages available');
  704.         $89 : writeln('no pages requested');
  705.         $8A : writeln('logical page outside range assigned to handle');
  706.         $8B : writeln('invalid physical page number');
  707.         $8C : writeln('page map hardware state save area full');
  708.         $8D : writeln('mapping context already in save area');
  709.         $8E : writeln('mapping context not in save area');
  710.         $8F : writeln('undefined subfunction parameter')
  711.         else
  712.             unknown('expanded memory error', a, 2)
  713.     end
  714. end;
  715.  
  716. begin (* procedure page_03 *)
  717.     caption2('Total conventional memory (bytes)');
  718.     writeln(DOSmem : 6);
  719.     caption2('Free conventional memory (bytes) ');
  720.     writeln(DOSmem - longint(prefixseg) shl 4 : 6);
  721.     caption2('Extended memory (bytes)        ');
  722.     with regs do begin
  723.         AH := $88;
  724.         intr($15, regs);
  725.         if nocarry then begin
  726.             writeln(longint(AX) shl 10 : 8);
  727.             caption3('XMM installed');
  728.             AX := $4300;
  729.             intr($2F, regs);
  730.             if nocarry and (AL = $80) then begin
  731.                 writeln('yes');
  732.                 caption3('XMM entry address');
  733.                 AX := $4310;
  734.                 intr($2F, regs);
  735.                 if nocarry then
  736.                     segofs2(ES, BX)
  737.                 else
  738.                     dontknow2
  739.             end else
  740.                 writeln('no')
  741. (* PC Magazine 8:12 pg. 321 *)
  742.         end else
  743.             writeln('     N/A')
  744.     end;
  745.     caption2('Expanded memory');
  746.     if longint(intvec[EMMint]) <> $00000000 then begin
  747.         writeln;
  748.         caption3('Interrupt vector');
  749.         xlong := longint(intvec[EMMint]);
  750.         xword1 := xlong shr 16;
  751.         xword2 := xlong and $0000FFFF;
  752.         segofs2(xword1, xword2);
  753.         caption3('Driver');
  754.         xstring := '';
  755.         for i := $000A to $0011 do
  756.             xstring := xstring + showchar(chr(mem[xword1 : i]));
  757.         write(xstring);
  758.         if xstring = qEMMdrvr then begin
  759.             writeln;
  760.             caption3('Manager status');
  761.             with regs do begin
  762.                 AH := $40;
  763.                 intr(EMMint, regs);
  764.                 if AH = $00 then
  765.                     writeln('OK')
  766.                 else
  767.                     EMMerr(AH);
  768.                 caption3('Page frame segment');
  769.                 AH := $41;
  770.                 intr(EMMint, regs);
  771.                 if AH = $00 then
  772.                     writeln(hex(BX, 4))
  773.                 else
  774.                     EMMerr(AH);
  775.                 caption3('Total EMS memory (16K pages)');
  776.                 AH := $42;
  777.                 intr(EMMint, regs);
  778.                 if AH = $00 then
  779.                     writeln(DX : 3)
  780.                 else
  781.                     EMMerr(AH);
  782.                 caption3('Free EMS memory (16K pages) ');
  783.                 if AH = $00 then
  784.                     writeln(BX : 3)
  785.                 else
  786.                     EMMerr(AH);
  787.                 caption3('EMM version');
  788.                 AH := $46;
  789.                 intr(EMMint, regs);
  790.                 if AH = $00 then
  791.                     writeln(AL shr 4, chr(country[9]), AL and $0F)
  792.                 else
  793.                     EMMerr(AH);
  794.                 caption1('  Handle   16K pages');
  795.                 writeln;
  796.                 AH := $4D;
  797.                 ES := seg(EMMarray);
  798.                 DI := ofs(EMMarray);
  799.                 intr(EMMint, regs);
  800.                 if AH = $00 then
  801.                     if BX > $0000 then begin
  802.                         window(3, wherey + hi(windmin), twidth, tlength - 2);
  803.                         for i := 1 to BX do begin
  804.                             pause1;
  805.                             writeln(hex(EMMarray[2 * i - 2], 4), '     '
  806.                                 , EMMarray[2 * i - 1] : 3)
  807.                         end
  808.                     end else
  809.                         writeln('  (no active handles)')
  810.                 else
  811.                     EMMerr(AH)
  812.             end
  813.         end else
  814.             dontknow2
  815.     end else
  816.         writeln('(none)')
  817. end;
  818.  
  819. (****************************************************************************)
  820.  
  821. procedure page_04;
  822.  
  823. var
  824.     xbyte : byte;
  825.     xword1 : word;
  826.     xword2 : word;
  827.     xword3 : word;
  828.     xword4 : word;
  829.  
  830. procedure showMCB(MCB, ownerPID, parent, size : word);
  831.  
  832. var
  833.     i : word;
  834.     xchar : char;
  835.     xlong1 : longint;
  836.     xlong2 : longint;
  837.     xlong3 : longint;
  838.     xstring : string;
  839.     xword : word;
  840.  
  841. begin
  842.     xlong1 := longint(size) shl 4;
  843.     xword := memw[ownerPID : $002C];
  844.     if ownerPID = $0008 then
  845.         xstring := 'IBMDOS.COM'
  846.     else if ownerPID = parent then
  847.         xstring := 'COMMAND.COM'
  848. (* BIX ms.dos/secrets #1496 *)
  849. (* Software Tools #145, p. 56 *)
  850.     else if (ownerPID = $0000) or (ownerPID = prefixseg) then
  851.         xstring := '(free)'
  852.     else begin
  853.         i := 0;
  854.         while memw[xword : i] > $0000 do
  855.             inc(i);
  856.         inc(i, 4);
  857.         xstring := '';
  858.         xchar := chr(mem[xword : i]);
  859.         while xchar in pchar do begin
  860.             if xchar in dirsep then
  861.                 xstring := ''
  862.             else
  863.                 xstring := xstring + xchar;
  864.             inc(i);
  865.             xchar := chr(mem[xword : i])
  866.         end;
  867.         if xchar > #0 then
  868.             xstring := ''
  869.     end;
  870.     write(hex(MCB, 4), '   ', hex(ownerPID, 4), '   ', hex(parent, 4), '     '
  871.         , xlong1 : 6, '   ');
  872.     if xword = MCB + 1 then
  873.         write(' ■ ')
  874.     else
  875.         write('   ');
  876.     write('   ', xstring);
  877.     if MCB + 1 = ownerPID then begin
  878.         for i := length(xstring) + 1 to 12 do
  879.             write(' ');
  880.         write('  ');
  881.         xlong2 := longint(ownerPID) shl 4;
  882.         for i := $00 to $FF do begin
  883.             xlong3 := longint(intvec[i]) and $FFFF0000 shr 12
  884.                 + longint(intvec[i]) and $0000FFFF;
  885.             if (xlong2 <= xlong3) and (xlong3 <= xlong2 + xlong1) then begin
  886.                 if wherex > twidth - 3 then begin
  887.                     writeln;
  888.                     pause1;
  889.                     write('                                                  '
  890.                         , '  ')
  891.                 end;
  892.                 write(' ', hex(i, 2))
  893.             end
  894.         end
  895.     end;
  896.     writeln
  897. end;
  898.  
  899. begin (* procedure page_04 *)
  900.     caption1('MCB    PSP    Parent     Size   Env   Owner'
  901.         + '          Interrupts');
  902.     writeln;
  903.     window(1, wherey + hi(windmin), twidth, tlength - 2);
  904.     xword1 := memw[devseg : devofs - $0002];
  905.     repeat
  906.         xbyte := mem[xword1 : $0000];
  907.         xword2 := memw[xword1 : $0001];
  908.         xword3 := memw[xword2 : $0016];
  909.         pause1;
  910.         case xbyte of
  911.             $4D : begin
  912.                 xword4 := memw[xword1 : $0003];
  913.                 showMCB(xword1, xword2, xword3, xword4);
  914.                 inc(xword1, 1 + xword4)
  915.             end;
  916.             $5A : begin
  917.                 xword4 := DOSmem shr 4 - xword1 - 1;
  918.                 showMCB(xword1, xword2, xword3, xword4)
  919.             end else
  920.                 unknown('MCB status', xbyte, 2)
  921.         end
  922.     until xbyte <> $4D
  923. (* PC Magazine 6:14 p.425 *)
  924. end;
  925.  
  926. (****************************************************************************)
  927.  
  928. procedure page_05;
  929.  
  930. var
  931.     i : byte;
  932.     xbyte : byte;
  933.     xint1 : integer;
  934.     xint2 : integer;
  935.     xword : word;
  936.  
  937. procedure showdisp(a : string; b : byte);
  938.  
  939. begin
  940.     caption2(a);
  941.     case b of
  942.         $00 : writeln('(none)');
  943.         $01 : writeln('MDA + 5151');
  944.         $02 : writeln('CGA + 5153/5154');
  945.         $03 : writeln('(reserved)');
  946.         $04 : writeln('EGA + 5153/5154');
  947.         $05 : writeln('EGA 5151');
  948.         $06 : writeln('PGA + 5175');
  949.         $07 : writeln('VGA + analog monochrome');
  950.         $08 : writeln('VGA + analog color');
  951.         $09 : writeln('(reserved)');
  952.         $0A : writeln('MCGA + digital color');
  953.         $0B : writeln('MCGA + digital monochrome');
  954.         $0C : writeln('MCGA + analog color');
  955.         $0D..$FE : writeln('(reserved)');
  956.         $FF : dontknow2
  957.     end
  958. end;
  959.  
  960. procedure showcolor(a : byte);
  961.  
  962. begin
  963.     case a of
  964.         black            : write('black');
  965.         blue            : write('blue');
  966.         green            : write('green');
  967.         cyan            : write('cyan');
  968.         red                : write('red');
  969.         magenta            : write('magenta');
  970.         brown            : write('brown');
  971.         lightgray        : write('light gray');
  972.         darkgray        : write('dark gray');
  973.         lightblue        : write('light blue');
  974.         lightgreen        : write('light green');
  975.         lightcyan        : write('light cyan');
  976.         lightred        : write('light red');
  977.         lightmagenta    : write('light magenta');
  978.         yellow            : write('yellow');
  979.         white            : write('white')
  980.         else
  981.             unknown('color', a, 2)
  982.     end
  983. end;
  984.  
  985. begin (* procedure page_05 *)
  986.     with regs do begin
  987.         AX := $1A00;
  988.         intr($10, regs);
  989.         if AL = $1A then begin
  990.             showdisp('Active video subsystem  ', BL);
  991.             showdisp('Inactive video subsystem', BH)
  992.         end
  993.     end;
  994.     caption2('Initial video mode');
  995.     case equip and $0030 of
  996.         $0000 : writeln('No display');
  997.         $0010 : writeln('40 x 25 color');
  998.         $0020 : writeln('80 x 25 color');
  999.         $0030 : writeln('80 x 25 monochrome')
  1000.     end;
  1001.     caption2('Current video mode');
  1002.     xbyte := lo(lastmode);
  1003.     write(xbyte, ' ');
  1004.     case xbyte of
  1005.         $00 : writeln('(40 x 25 b/w text)');
  1006.         $01 : writeln('(40 x 25 color text)');
  1007.         $02 : writeln('(80 x 25 b/w text)');
  1008.         $03 : writeln('(80 x 25 color text)');
  1009.         $04 : writeln('(320 x 200 4 colors)');
  1010.         $05 : writeln('(320 x 200 4 colors, no color burst)');
  1011.         $06 : writeln('(640 x 200 2 colors)');
  1012.         $07 : writeln('(MDA text)');
  1013.         $08 : writeln('(160 x 200 16 colors)');
  1014.         $09 : writeln('(320 x 200 16 colors)');
  1015.         $0A : writeln('(640 x 200 4 colors)');
  1016.         $0D : writeln('(320 x 200 16 colors)');
  1017.         $0E : writeln('(640 x 200 16 colors)');
  1018.         $0F : writeln('(640 x 350 monochrome)');
  1019.         $10 : writeln('(640 x 350 16 colors)');
  1020.         $11 : writeln('(640 x 480 2 colors)');
  1021.         $12 : writeln('(640 x 480 16 colors)');
  1022.         $13 : writeln('(640 x 480 256 colors)')
  1023.         else
  1024.             unknown('video mode', xbyte, 2)
  1025.     end;
  1026.     caption2('Current display page');
  1027.     writeln(vidpg);
  1028.     caption2('Graphics modes');
  1029.     getmoderange(graphdriver, xint1, xint2);
  1030.     if graphresult = grok then
  1031.         writeln(xint2 + 1 - xint1)
  1032.     else
  1033.         writeln(0);
  1034.     caption2('Video buffer (offset)');
  1035.     writeln(hex(memw[BIOSdseg : $004E], 4));
  1036.     caption2('Video buffer size (bytes)');
  1037.     writeln(memw[BIOSdseg : $004C]);
  1038.     caption2('Active display port');
  1039.     xword := memw[BIOSdseg : $0063];
  1040.     write('$', hex(xword, 3), ' ');
  1041.     if xword = $03B4 then
  1042.         writeln('(monochrome)')
  1043.     else if xword = $03D4 then
  1044.         writeln('(color)')
  1045.     else
  1046.         dontknow2;
  1047.     caption2('CRT mode register');
  1048.     writeln('$', hex(mem[BIOSdseg : $0065], 2));
  1049.     caption2('Current palette');
  1050.     writeln('$', hex(mem[BIOSdseg : $0066], 2));
  1051.     caption2('Colors');
  1052.     caption1('·');
  1053.     for i := black to white do begin
  1054.         textcolor(i);
  1055.         write('█')
  1056.     end;
  1057.     caption1('·');
  1058.     writeln;
  1059.     caption2('Current colors');
  1060.     if (attrsave and $80) = $80 then
  1061.         write('blinking ');
  1062.     showcolor(attrsave and $0F);
  1063.     write(' on ');
  1064.     showcolor(attrsave and $70 shr 4);
  1065.     writeln;
  1066.     caption2('Text rows');
  1067.     writeln(tlength);
  1068.     caption2('Text columns');
  1069.     writeln(twidth);
  1070.     if graphdriver in [EGA, MCGA, VGA] then begin
  1071.         caption2('Scan lines/character');
  1072.         with regs do begin
  1073.             AX := $1130;
  1074.             BH := $00;
  1075.             intr($10, regs);
  1076.             writeln(CX)
  1077.         end
  1078.     end;
  1079.     caption2('Cursor scan lines');
  1080.     with regs do begin
  1081.         AH := $03;
  1082.         BH := vidpg;
  1083.         intr($10, regs);
  1084.         writeln(CH, '-', CL)
  1085.     end
  1086. end;
  1087.  
  1088. (****************************************************************************)
  1089.  
  1090. procedure page_06;
  1091.  
  1092. var
  1093.     i : byte;
  1094.     VGAbuf : array[$00..$10] of byte;
  1095.     xbyte : byte;
  1096.     xword1 : word;
  1097.     xword2 : word;
  1098.     xword3 : word;
  1099.     xword4 : word;
  1100.  
  1101. procedure captfont;
  1102.  
  1103. begin
  1104.     caption1('Font           Address');
  1105.     writeln;
  1106.     write('INT 1FH        ');
  1107.     segofs2(longint(intvec[$1F]) shr 16, longint(intvec[$1F]) and $0000FFFF)
  1108. end;
  1109.  
  1110. procedure showfont(a : byte);
  1111.  
  1112. begin
  1113.     with regs do begin
  1114.         case a of
  1115.             $00 : write('INT 1FH     ');
  1116.             $01 : write('INT 43H     ');
  1117.             $02 : write('ROM 8x14    ');
  1118.             $03 : write('ROM 8x8 (lo)');
  1119.             $04 : write('ROM 8x8 (hi)');
  1120.             $05 : write('ROM 9x14    ');
  1121.             $06 : write('ROM 8x16    ');
  1122.             $07 : write('ROM 9x16    ')
  1123.         end;
  1124.         write('   ');
  1125.         AX := $1130;
  1126.         BH := a;
  1127.         intr($10, regs);
  1128.         segofs2(ES, BP)
  1129.     end
  1130. end;
  1131.  
  1132. procedure int101210;
  1133.  
  1134. begin
  1135.     with regs do begin
  1136.         AH := $12;
  1137.         BL := $10;
  1138.         intr($10, regs);
  1139.         caption2('Display type');
  1140.         case BH of
  1141.             $00 : writeln('color');
  1142.             $01 : writeln('monochrome')
  1143.             else
  1144.                 unknown('display', BH, 2)
  1145.         end;
  1146.         caption2('Memory');
  1147.         case BL of
  1148.             $00 : writeln('64K');
  1149.             $01 : writeln('128K');
  1150.             $02 : writeln('192K');
  1151.             $03 : writeln('256K')
  1152.             else
  1153.                 unknown('size', BL, 2)
  1154.         end;
  1155.         caption2('Feature bits');
  1156.         writeln(bin4(CH and $0F));
  1157.         caption2('DIP switches');
  1158.         writeln(bin4(CL and $0F))
  1159.     end
  1160. end;
  1161.  
  1162. begin (* procedure page_06 *)
  1163.     caption2('Display adapter');
  1164.     case graphdriver of
  1165.         CGA : begin
  1166.             writeln('CGA');
  1167.             captfont
  1168.         end;
  1169.         MCGA : begin
  1170.             writeln('MCGA');
  1171.             captfont;
  1172.             showfont($01);
  1173.             showfont($03);
  1174.             showfont($04);
  1175.             showfont($06)
  1176.         end;
  1177.         EGA..EGAmono : begin
  1178.             writeln('EGA');
  1179.             captfont;
  1180.             showfont($01);
  1181.             showfont($02);
  1182.             showfont($03);
  1183.             showfont($04);
  1184.             showfont($05);
  1185.             int101210;
  1186.             xbyte := mem[BIOSdseg : $0087];
  1187.             caption2('Mode change preserves screen buffer');
  1188.             yesorno2(xbyte and $80 = $80);
  1189.             caption2('EGA active');
  1190.             yesorno2(xbyte and $08 = $00);
  1191.             caption2('Wait for display enable');
  1192.             yesorno2(xbyte and $04 = $04);
  1193.             caption2('CGA cursor emulation');
  1194.             yesorno2(xbyte and $01 = $00);
  1195. (* PC Magazine 6:12 p.326 *)
  1196.             caption2('Save area                    ');
  1197.             xword1 := memw[BIOSdseg : $00AA];
  1198.             xword2 := memw[BIOSdseg : $00A8];
  1199.             segofs2(xword1, xword2);
  1200. (* PC Tech Journal 3:4 p.65 *)
  1201.             caption2('Video parameter table        ');
  1202.             segofs2(memw[xword1 : xword2 + 2], memw[xword1 : xword2]);
  1203.             caption2('Dynamic save area            ');
  1204.             xword3 := memw[xword1 : xword2 + 6];
  1205.             xword4 := memw[xword1 : xword2 + 4];
  1206.             if (xword3 > $0000) or (xword4 > $0000) then
  1207.                 segofs2(xword3, xword4)
  1208.             else
  1209.                 writeln('(none)');
  1210.             caption2('Auxiliary character generator');
  1211.             xword3 := memw[xword1 : xword2 + 10];
  1212.             xword4 := memw[xword1 : xword2 + 8];
  1213.             if (xword3 > $0000) or (xword4 > $0000) then
  1214.                 segofs2(xword3, xword4)
  1215.             else
  1216.                 writeln('(none)');
  1217.             caption2('Graphics mode auxiliary table');
  1218.             xword3 := memw[xword1 : xword2 + 14];
  1219.             xword4 := memw[xword1 : xword2 + 12];
  1220.             if (xword3 > $0000) or (xword4 > $0000) then
  1221.                 segofs1(xword3, xword4)
  1222.             else
  1223.                 write('(none)')
  1224. (* PC Tech Journal 3:4 p.67 *)
  1225.         end;
  1226.         hercmono : begin
  1227.             writeln('Hercules or MDA');
  1228.             captfont
  1229.         end;
  1230.         IBM8514 : begin
  1231.             writeln('IBM 8514');
  1232.             captfont
  1233.         end;
  1234.         ATT400 : begin
  1235.             writeln('AT&T 400');
  1236.             captfont
  1237.         end;
  1238.         VGA : begin
  1239.             writeln('VGA');
  1240.             captfont;
  1241.             showfont($01);
  1242.             showfont($02);
  1243.             showfont($03);
  1244.             showfont($04);
  1245.             showfont($05);
  1246.             showfont($06);
  1247.             showfont($07);
  1248.             int101210;
  1249.             with regs do begin
  1250.                 AX := $1009;
  1251.                 ES := seg(VGAbuf);
  1252.                 DX := ofs(VGAbuf);
  1253.                 intr($10, regs)
  1254.             end;
  1255.             caption2('Palette registers');
  1256.             for i := $00 to $0F do
  1257.                 write(hex(VGAbuf[i], 2), ' ');
  1258.             writeln;
  1259.             caption2('Border color');
  1260.             writeln(hex(VGAbuf[$10], 2));
  1261.             caption2('Color page');
  1262.             with regs do begin
  1263.                 AX := $101A;
  1264.                 intr($10, regs);
  1265.                 writeln('$', hex(BH, 2));
  1266.                 caption2('Paging mode');
  1267.                 case BL of
  1268.                     $00 : writeln('4 pages of 64 registers');
  1269.                     $01 : writeln('16 pages of 16 registers')
  1270.                     else
  1271.                         unknown('mode', BL, 2)
  1272.                 end
  1273.             end
  1274.         end;
  1275.         PC3270 : begin
  1276.             writeln('3270 PC');
  1277.             captfont
  1278.         end else
  1279.             unknown('adapter', graphdriver, 4)
  1280.     end
  1281. end;
  1282.  
  1283. (****************************************************************************)
  1284.  
  1285. procedure page_07;
  1286.  
  1287. const
  1288.     mouseint = $33;
  1289.  
  1290. var
  1291.     xbyte : byte;
  1292.     xword1 : word;
  1293.     xword2 : word;
  1294.  
  1295. begin
  1296.     caption2('Keyboard');
  1297.     writeln;
  1298.     caption3('BIOS support for enhanced keyboard');
  1299.     with regs do begin
  1300.         AH := $02;
  1301.         intr($16, regs);
  1302.         xbyte := AL;
  1303.         AX := $1200 + xbyte xor $FF;
  1304.         intr($16, regs);
  1305.         if AL = xbyte then begin
  1306.             writeln('yes');
  1307.             caption3('Enhanced keyboard present');
  1308.             yesorno2(mem[BIOSdseg : $0096] and $10 = $10)
  1309.         end else
  1310.             writeln('no');
  1311. (* PC Magazine 6:15 p.378 *)
  1312.         AH := $02;
  1313.         intr($16, regs);
  1314.         caption3('Insert');
  1315.         offoron(AL and $80 = $80);
  1316.         caption1('   Caps Lock: ');
  1317.         offoron(AL and $40 = $40);
  1318.         caption1('   Num Lock: ');
  1319.         offoron(AL and $20 = $20);
  1320.         caption1('   Scroll Lock: ');
  1321.         offoron(AL and $10 = $10);
  1322.         writeln
  1323.     end;
  1324.     caption3('Buffer');
  1325.     xword1 := memw[BIOSdseg : $0080];
  1326.     segofs1(BIOSdseg, xword1);
  1327.     xword2 := memw[BIOSdseg : $0082];
  1328.     writeln('-', hex(xword2, 4));
  1329.     caption3('Buffer size (keystrokes)');
  1330.     writeln((xword2 - xword1) shr 1 - 1);
  1331.     caption2('Internal modem/serial printer');
  1332.     yesorno2(equip and $2000 = $2000);
  1333.     caption2('Game port');
  1334.     yesorno2(equip and $1000 = $1000);
  1335.     caption2('Mouse');
  1336.     with regs do begin
  1337.         AX := $0000;
  1338.         intr(mouseint, regs);
  1339.         if AX = $FFFF then begin
  1340.             writeln('yes');
  1341.             caption3('Buttons');
  1342.             writeln(BX);
  1343.             caption3('Save state buffer size (bytes)');
  1344.             AX := $0015;
  1345.             BX := $FFFF;
  1346.             intr(mouseint, regs);
  1347.             if BX < $FFFF then
  1348.                 writeln(BX)
  1349.             else
  1350.                 dontknow2;
  1351.             caption3('Mickeys/pixel (horizontal)');
  1352.             AX := $001B;
  1353.             BX := $FFFF;
  1354.             CX := $FFFF;
  1355.             DX := $FFFF;
  1356.             intr(mouseint, regs);
  1357.             if BX < $FFFF then
  1358.                 writeln(BX : 5)
  1359.             else
  1360.                 dontknow2;
  1361.             caption3('Mickeys/pixel (vertical)  ');
  1362.             if CX < $FFFF then
  1363.                 writeln(CX : 5)
  1364.             else
  1365.                 dontknow2;
  1366.             caption3('Double speed threshold');
  1367.             if DX < $FFFF then
  1368.                 writeln(DX)
  1369.             else
  1370.                 dontknow2;
  1371.             caption3('Current display page');
  1372.             AX := $001E;
  1373.             BX := $FFFF;
  1374.             intr(mouseint, regs);
  1375.             if BX < $FFFF then
  1376.                 writeln(BX)
  1377.             else
  1378.                 dontknow2;
  1379.             caption3('Language');
  1380.             AX := $0023;
  1381.             BX := $FFFF;
  1382.             intr(mouseint, regs);
  1383.             if BX < $FFFF then
  1384.                 if BX = $0000 then
  1385.                     writeln('English')
  1386.                 else if BX = $0001 then
  1387.                     writeln('French')
  1388.                 else if BX = $0002 then
  1389.                     writeln('Dutch')
  1390.                 else if BX = $0003 then
  1391.                     writeln('German')
  1392.                 else if BX = $0004 then
  1393.                     writeln('Swedish')
  1394.                 else if BX = $0005 then
  1395.                     writeln('Finnish')
  1396.                 else if BX = $0006 then
  1397.                     writeln('Spanish')
  1398.                 else if BX = $0007 then
  1399.                     writeln('Portuguese')
  1400.                 else if BX = $0008 then
  1401.                     writeln('Italian')
  1402.                 else
  1403.                     unknown('language', BX, 4)
  1404.             else
  1405.                 dontknow2;
  1406.             caption3('Driver version');
  1407.             AX := $0024;
  1408.             BX := $FFFF;
  1409.             CX := $FFFF;
  1410.             intr(mouseint, regs);
  1411.             if BX < $FFFF then begin
  1412.                 write(BH, chr(country[9]));
  1413.                 zeropad(BL)
  1414.             end else
  1415.                 dontknow1;
  1416.             writeln;
  1417.             caption3('Type');
  1418.             if CX < $FFFF then
  1419.                 case CH of
  1420.                     $01 : writeln('bus');
  1421.                     $02 : writeln('serial');
  1422.                     $03 : writeln('InPort');
  1423.                     $04 : writeln('PS/2');
  1424.                     $05 : writeln('HP')
  1425.                     else
  1426.                         unknown('mouse', CH, 2)
  1427.                 end
  1428.             else
  1429.                 dontknow2;
  1430.             caption3('Interrupt');
  1431.             if CX < $FFFF then
  1432.                 case CL of
  1433.                     $00 : writeln('PS/2');
  1434.                     $02..$05, $07 : writeln('IRQ', CL)
  1435.                     else
  1436.                         unknown('interrupt', CL, 2)
  1437.                 end
  1438.             else
  1439.                 dontknow2
  1440.         end else
  1441.             writeln('no')
  1442.     end
  1443. end;
  1444.  
  1445. (****************************************************************************)
  1446.  
  1447. procedure page_08;
  1448.  
  1449. const
  1450.     tick2 = 115200;
  1451.  
  1452. var
  1453.     i : byte;
  1454.     xbyte1 : byte;
  1455.     xbyte2 : byte;
  1456.     xword : word;
  1457.     y : byte;
  1458.  
  1459.  
  1460. begin
  1461.     y := wherey + hi(windmin);
  1462.     window(1, y, 30, tlength - 2);
  1463.     caption2('Printers');
  1464.     xbyte1 := equip and $C000 shr 14;
  1465.     writeln(xbyte1);
  1466.     if xbyte1 > 0 then begin
  1467.         caption3('Device');
  1468.         writeln;
  1469.         caption3('Base port');
  1470.         writeln;
  1471.         caption3('Timeout');
  1472.         writeln;
  1473.         caption3('Busy');
  1474.         writeln;
  1475.         caption3('ACK');
  1476.         writeln;
  1477.         caption3('Paper out');
  1478.         writeln;
  1479.         caption3('Selected');
  1480.         writeln;
  1481.         caption3('I/O error');
  1482.         writeln;
  1483.         caption3('Timed out');
  1484.         for i := 1 to xbyte1 do begin
  1485.             window(9 + 6 * i, y + 1, 15 + 6 * i, tlength - 2);
  1486.             writeln('LPT', i);
  1487.             writeln('$', hex(memw[BIOSdseg : 2 * i + 6], 3));
  1488.             writeln(mem[BIOSdseg : $0077 + i]);
  1489.             with regs do begin
  1490.                 AH := $02;
  1491.                 DX := 0;
  1492.                 intr($17, regs);
  1493.                 yesorno2(AH and $80 = $00);
  1494.                 yesorno2(AH and $40 = $40);
  1495.                 yesorno2(AH and $20 = $20);
  1496.                 yesorno2(AH and $10 = $10);
  1497.                 yesorno2(AH and $08 = $08);
  1498.                 yesorno2(AH and $01 = $01)
  1499.             end
  1500.         end
  1501.     end;
  1502.     window(twidth - 42, y, twidth, tlength - 2);
  1503.     caption2('Serial ports');
  1504.     xbyte1 := equip and $0E00 shr 9;
  1505.     writeln(xbyte1);
  1506.     if xbyte1 > 0 then begin
  1507.         if xbyte1 > 4 then
  1508.             xbyte1 := 4;
  1509.         caption3('Device');
  1510.         writeln;
  1511.         caption3('Base port');
  1512.         writeln;
  1513.         caption3('Timeout');
  1514.         writeln;
  1515.         caption3('Baud rate');
  1516.         writeln;
  1517.         caption3('Data bits');
  1518.         writeln;
  1519.         caption3('Parity');
  1520.         writeln;
  1521.         caption3('Stop bits');
  1522.         writeln;
  1523.         caption3('Break');
  1524.         writeln;
  1525.         caption3('RLSD');
  1526.         writeln;
  1527.         caption3('RI');
  1528.         writeln;
  1529.         caption3('DSR');
  1530.         writeln;
  1531.         caption3('CTS');
  1532.         writeln;
  1533.         caption3('dRLSD');
  1534.         writeln;
  1535.         caption3('-dRI');
  1536.         writeln;
  1537.         caption3('dDSR');
  1538.         writeln;
  1539.         caption3('dCTS');
  1540.         for i := 1 to xbyte1 do begin
  1541.             window(twidth - 35 + 7 * i, y + 1, twidth - 28 + 7 * i
  1542.                 , tlength - 2);
  1543.             writeln('COM', i);
  1544.             xword := memw[BIOSdseg : 2 * i - 2];
  1545.             writeln('$', hex(xword, 3));
  1546.             writeln(mem[BIOSdseg : $007B + i]);
  1547.             xbyte2 := port[xword + 3];
  1548.             port[xword + 3] := xbyte2 or $80;
  1549.             writeln(tick2 / cbw(port[xword], port[xword + 1]) : 0 : 0);
  1550.             port[xword + 3] := xbyte2;
  1551.             case xbyte2 and $03 of
  1552.                 $00 : writeln('5');
  1553.                 $01 : writeln('6');
  1554.                 $02 : writeln('7');
  1555.                 $03 : writeln('8')
  1556.             end;
  1557.             case xbyte2 and $38 of
  1558.                 $00, $10, $20, $30 : writeln('none');
  1559.                 $08 : writeln('odd');
  1560.                 $18 : writeln('even');
  1561.                 $28 : writeln('mark');
  1562.                 $38 : writeln('space')
  1563.             end;
  1564.             case xbyte2 and $07 of
  1565.                 $00..$03 : writeln('1');
  1566.                 $04 : writeln('1.5');
  1567.                 $05..$07 : writeln('2')
  1568.             end;
  1569.             yesorno2(xbyte2 and $40 = $40);
  1570.             with regs do begin
  1571.                 AH := $03;
  1572.                 DX := i - 1;
  1573.                 intr($14, regs);
  1574.                 yesorno2(AL and $80 = $80);
  1575.                 yesorno2(AL and $40 = $40);
  1576.                 yesorno2(AL and $20 = $20);
  1577.                 yesorno2(AL and $10 = $10);
  1578.                 yesorno2(AL and $08 = $08);
  1579.                 yesorno2(AL and $04 = $04);
  1580.                 yesorno2(AL and $02 = $02);
  1581.                 yesorno2(AL and $01 = $01)
  1582.             end
  1583.         end
  1584.     end
  1585. end;
  1586.  
  1587. (****************************************************************************)
  1588.  
  1589. procedure page_09;
  1590.  
  1591. const
  1592.     filesmax = 256;
  1593.  
  1594. var
  1595.     f : array[1..filesmax] of file;
  1596.     i : 0..filesmax;
  1597.     j : 1..filesmax;
  1598.     xbool : boolean;
  1599.     xbyte : byte;
  1600.     xchar : char;
  1601.     xstring1 : string;
  1602.     xstring2 : string;
  1603.     xword1 : word;
  1604.     xword2 : word;
  1605.     xword3 : word;
  1606.     xword4 : word;
  1607.     xword5 : word;
  1608.     y : byte;
  1609.  
  1610. procedure showecho(a : word);
  1611.  
  1612. var
  1613.     xbyte : byte;
  1614.  
  1615. begin
  1616.     xbyte := mem[DOScseg : a];
  1617.     case xbyte of
  1618.         $00 : writeln('off');
  1619.         $FF : writeln('on')
  1620.         else
  1621.             unknown('status', xbyte, 2)
  1622.     end
  1623. end;
  1624.  
  1625. begin (* procedure page_09 *)
  1626.     y := wherey + hi(windmin);
  1627.     window(1, y, twidth div 2, tlength - 2);
  1628.     caption2('DOS version');
  1629.     with regs do begin
  1630.         AH := $30;
  1631.         MSDOS(regs);
  1632.         write(AL, chr(country[9]));
  1633.         zeropad(AH);
  1634.         writeln;
  1635.         caption2('OEM serial # ');
  1636.         writeln(BH);
  1637.         caption2('User serial #');
  1638.         writeln(longint(BL) shl 16 + CX)
  1639.     end;
  1640.     caption2('System date');
  1641.     getdate(xword1, xword2, xword3, xword4);
  1642.     if xword4 = 0 then
  1643.         write('Sunday')
  1644.     else if xword4 = 1 then
  1645.         write('Monday')
  1646.     else if xword4 = 2 then
  1647.         write('Tuesday')
  1648.     else if xword4 = 3 then
  1649.         write('Wednesday')
  1650.     else if xword4 = 4 then
  1651.         write('Thursday')
  1652.     else if xword4 = 5 then
  1653.         write('Friday')
  1654.     else if xword4 = 6 then
  1655.         write('Saturday')
  1656.     else
  1657.         write('(', hex(xword4, 4), ')');
  1658.     write(', ');
  1659.     xword5 := cbw(country[0], country[1]);
  1660.     xchar := chr(country[11]);
  1661.     if xword5 = $0000 then
  1662.         writeln(xword2, xchar, xword3, xchar, xword1)
  1663.     else if xword5 = $0001 then
  1664.         writeln(xword3, xchar, xword2, xchar, xword1)
  1665.     else if xword5 = $0002 then
  1666.         writeln(xword1, xchar, xword2, xchar, xword3)
  1667.     else
  1668.         writeln(xword2, xchar, xword3, xchar, xword1);
  1669.     caption2('System time');
  1670.     gettime(xword1, xword2, xword3, xword4);
  1671.     zeropad(xword1);
  1672.     write(chr(country[13]));
  1673.     zeropad(xword2);
  1674.     write(chr(country[13]));
  1675.     zeropad(xword3);
  1676.     write(chr(country[9]));
  1677.     zeropad(xword4);
  1678.     writeln;
  1679.     caption2('Command load paragraph');
  1680.     writeln(hex(prefixseg, 4));
  1681.     caption2('Ctrl-C check');
  1682.     getcbreak(xbool);
  1683.     offoron(xbool);
  1684.     writeln;
  1685.     caption2('Disk verify');
  1686.     getverify(xbool);
  1687.     offoron(xbool);
  1688.     writeln;
  1689.     caption2('Switch prefix character');
  1690.     writeln(switchar);
  1691.     caption2('\DEV\ prefix for devices');
  1692.     with regs do begin
  1693.         AX := $3702;
  1694.         MSDOS(regs);
  1695.         if DL = $00 then
  1696.             writeln('required')
  1697.         else
  1698.             writeln('optional')
  1699.     end;
  1700.     caption2('Reset boot');
  1701.     xword1 := memw[BIOSdseg : $72];
  1702.     if xword1 = $0000 then
  1703.         writeln('cold')
  1704.     else if (xword1 = $1234) or (xword1 = $1200) then
  1705.         writeln('bypass memory test')
  1706.     else if xword1 = $4321 then
  1707.         writeln('preserve memory')
  1708.     else if xword1 = $5678 then
  1709.         writeln('system suspended')
  1710.     else if xword1 = $9ABC then
  1711.         writeln('manufacturing test mode')
  1712.     else if xword1 = $ABCD then
  1713.         writeln('system POST loop mode')
  1714.     else
  1715.         unknown('flag', xword1, 4);
  1716. (* Byte 12:12 p.178 *)
  1717.     with regs do begin
  1718.         caption2('DOS critical flag');
  1719.         AX := $5D06;
  1720.         MSDOS(regs);
  1721.         segofs2(DS, SI)
  1722.     end;
  1723.     caption2('DOS busy flag    ');
  1724.     segofs2(DOScseg, DOScofs);
  1725.     caption2('Printer echo');
  1726.     case osminor of
  1727.         0..9 : dontknow2;
  1728.         10..39 : showecho($02AC)
  1729.         else
  1730.             dontknow2
  1731.     end;
  1732. (* BIX ms.dos/secrets #501 *)
  1733.     caption2('PrtSc status');
  1734.     xbyte := mem[BIOSdseg : $0100];
  1735.     case xbyte of
  1736.         $00 : writeln('ready');
  1737.         $01 : writeln('busy');
  1738.         $FF : writeln('error on last PrtSc')
  1739.         else
  1740.             unknown('status', xbyte, 2)
  1741.     end;
  1742.     caption2('Memory allocation');
  1743.     with regs do begin
  1744.         AX := $5800;
  1745.         MSDOS(regs);
  1746.         if AX = $0000 then
  1747.             writeln('first fit')
  1748.         else if AX = $0001 then
  1749.             writeln('best fit')
  1750.         else
  1751.             writeln('last fit')
  1752.     end;
  1753.     window(1 + twidth div 2, y, twidth, tlength - 2);
  1754.     caption2('DOS buffers');
  1755.     xword1 := 0;
  1756.     xword2 := memw[devseg : devofs + $0014];
  1757.     xword3 := memw[devseg : devofs + $0012];
  1758.     while (xword2 < $FFFF) or (xword3 < $FFFF) do begin
  1759.         inc(xword1);
  1760.         xword4 := memw[xword2 : xword3 + $0002];
  1761.         xword3 := memw[xword2 : xword3];
  1762.         xword2 := xword4
  1763.     end;
  1764.     writeln(xword1);
  1765.     caption2('Buffer size (bytes)');
  1766.     writeln(memw[devseg : devofs + $0010]);
  1767. (* BIX ms.dos/long.messages #228 *)
  1768.     caption2('File handle table');
  1769.     xword1 := memw[prefixseg : $0036];
  1770.     xword2 := memw[prefixseg : $0034];
  1771.     segofs2(xword1, xword2);
  1772.     caption2('File handle table length');
  1773.     writeln(mem[prefixseg : $0032] : 3);
  1774.     caption2('File handles used       ');
  1775.     i := 0;
  1776.     while mem[xword1 : xword2] < $FF do begin
  1777.         inc(i);
  1778.         inc(xword2)
  1779.     end;
  1780.     writeln(i : 3);
  1781.     caption1('File handles free');
  1782.     i := 0;
  1783.     xbool := false;
  1784.     xstring1 := getenv('comspec');
  1785.     repeat
  1786.         if i < filesmax then begin
  1787.             assign(f[i + 1], xstring1);
  1788.             reset(f[i + 1]);
  1789.             if ioresult = 0 then
  1790.                 inc(i)
  1791.             else begin
  1792.                 xbool := true;
  1793.                 caption2('       ');
  1794.                 writeln(i : 3)
  1795.             end
  1796.         end else begin
  1797.             xbool := true;
  1798.             caption2('');
  1799.             dontknow2
  1800.         end
  1801.     until xbool;
  1802.     for j := 1 to i do
  1803.         close(f[j]);
  1804.     caption2('Global code page');
  1805.     with regs do begin
  1806.         AX := $6601;
  1807.         MSDOS(regs);
  1808.         if AL = $01 then begin
  1809.             writeln;
  1810.             caption3('Active ');
  1811.             writeln(BX : 5);
  1812.             caption3('Default');
  1813.             writeln(DX : 5)
  1814.         end else
  1815.             writeln('N/A')
  1816.     end;
  1817.     caption2('Country code');
  1818.     writeln(ccode);
  1819.     caption2('Thousands separator character');
  1820.     writeln(chr(country[7]));
  1821.     caption2('Decimal separator character');
  1822.     writeln(chr(country[9]));
  1823.     caption2('Data-list separator character');
  1824.     writeln(chr(country[22]));
  1825.     caption2('Date format');
  1826.     xword1 := cbw(country[0], country[1]);
  1827.     xchar := chr(country[11]);
  1828.     if xword1 = $0000 then
  1829.         writeln('USA (mm', xchar, 'dd', xchar, 'yy)')
  1830.     else if xword1 = $0001 then
  1831.         writeln('Europe (dd', xchar, 'mm', xchar, 'yy)')
  1832.     else if xword1 = $0002 then
  1833.         writeln('Japan (yy', xchar, 'mm', xchar, 'dd)')
  1834.     else
  1835.         unknown('format', xword1, 4);
  1836.     caption3('Separator character');
  1837.     writeln(xchar);
  1838.     caption2('Time format');
  1839.     if (country[17] and $01) = $00 then
  1840.         write('12')
  1841.     else
  1842.         write('24');
  1843.     writeln('-hour');
  1844.     caption3('Separator character');
  1845.     writeln(chr(country[13]));
  1846.     caption2('Currency format');
  1847.     xstring1 := 'xxxx';
  1848.     insert(chr(country[7]), xstring1, 2);
  1849.     xstring1 := xstring1 + chr(country[9]);
  1850.     for i := 1 to country[16] do
  1851.         xstring1 := xstring1 + 'y';
  1852.     xstring2 := '';
  1853.     i := 2;
  1854.     xchar := chr(country[i]);
  1855.     while (i <= 6) and (xchar > #0) do begin
  1856.         xstring2 := xstring2 + xchar;
  1857.         inc(i);
  1858.         xchar := chr(country[i])
  1859.     end;
  1860.     case country[15] and $03 of
  1861.         $00 : xstring1 := xstring2 + xstring1;
  1862.         $01 : xstring1 := xstring1 + xstring2;
  1863.         $02 : xstring1 := xstring2 + ' ' + xstring1;
  1864.         $03 : xstring1 := xstring1 + ' ' + xstring2;
  1865.         $04 : begin
  1866.             delete(xstring1, 6, 1);
  1867.             insert(xstring2, xstring1, 6)
  1868.         end
  1869.     end;
  1870.     writeln(xstring1);
  1871.     caption2('Case map call address');
  1872.     segofs2(cbw(country[20], country[21]), cbw(country[18], country[19]))
  1873. end;
  1874.  
  1875. (****************************************************************************)
  1876.  
  1877. procedure page_10;
  1878.  
  1879. var
  1880.     i : word;
  1881.     xchar : char;
  1882.  
  1883. procedure muxint(a : string; b : byte);
  1884.  
  1885. begin
  1886.     caption3(a);
  1887.     with regs do begin
  1888.         AX := b shl 8;
  1889.         intr($2F, regs);
  1890.         if nocarry then
  1891.             case AL of
  1892.                 $00 : writeln('no, OK to install');
  1893.                 $01 : writeln('no, not OK to install');
  1894.                 $FF : writeln('yes')
  1895.                 else
  1896.                     unknown('status', AL, 2)
  1897.             end
  1898.         else
  1899.             writeln('N/A')
  1900.     end
  1901. end;
  1902.  
  1903. begin (* procedure page_10 *)
  1904.     caption2('Multiplex interrupt ($2F)');
  1905.     writeln;
  1906.     muxint('PRINT          ', $01);
  1907.     muxint('ASSIGN         ', $06);
  1908. (*
  1909. **    Byte 12:12 p. 176C, Duncan, and many others, all of whom mistakenly give
  1910. **    AH = $02
  1911. *)
  1912. (*
  1913.     muxint('DRIVER.SYS     ', $08);
  1914. *)
  1915.     muxint('SHARE          ', $10);
  1916. (*
  1917.     muxint('FASTOPEN       ', $12);
  1918. *)
  1919.     muxint('NLSFUNC        ', $14);
  1920.     muxint('GRAFTABL       ', $B0);
  1921. (*
  1922.     muxint('DISPLAY.SYS    ', $B0);
  1923. *)
  1924.     muxint('APPEND         ', $B7);
  1925. (*
  1926.     muxint('KEYB           ', $B8);
  1927. *)
  1928.     muxint('NETBIOS APPEND ', $87);
  1929.     muxint('NETBIOS NETWORK', $88);
  1930. (* Byte 12:12 p. 180.  PC Tech Journal 3:11 p.104 gives AH = $BB *)
  1931.     with regs do begin
  1932.         AX := $B700;
  1933.         intr($2F, regs);
  1934.         if AL = $FF then begin
  1935.             caption2('APPEND');
  1936.             writeln;
  1937.             caption3('Path');
  1938.             AX := $B704;
  1939.             intr($2F, regs);
  1940.             if nocarry then begin
  1941.                 xchar := chr(mem[ES : DI]);
  1942.                 while xchar > #0 do begin
  1943.                     write(xchar);
  1944.                     inc(DI);
  1945.                     xchar := chr(mem[ES : DI])
  1946.                 end;
  1947.                 writeln
  1948.             end else
  1949.                 dontknow2;
  1950.         end
  1951.     end;
  1952.     with regs do begin
  1953.         AX := $0100;
  1954.         intr($2F, regs);
  1955.         if AL = $FF then begin
  1956.             caption2('PRINT queue');
  1957.             AX := $0104;
  1958.             intr($2F, regs);
  1959.             xchar := chr(mem[DS : SI]);
  1960.             if xchar > #0 then begin
  1961.                 writeln;
  1962.                 window(3, wherey + hi(windmin), twidth, tlength - 2);
  1963.                 repeat
  1964.                     pause1;
  1965.                     i := SI;
  1966.                     xchar := chr(mem[DS : i]);
  1967.                     repeat
  1968.                         write(xchar);
  1969.                         inc(i);
  1970.                         xchar := chr(mem[DS : i])
  1971.                     until xchar = #0;
  1972.                     writeln;
  1973.                     inc(SI, 64);
  1974.                     xchar := chr(mem[DS : SI])
  1975.                 until xchar = #0
  1976.             end else
  1977.                 writeln('(empty)');
  1978.             AX := $0105;
  1979.             intr($2F, regs)
  1980.         end
  1981.     end
  1982. end;
  1983.  
  1984. (****************************************************************************)
  1985.  
  1986. procedure page_11;
  1987.  
  1988. begin
  1989.     caption2('Environment');
  1990.     window(3, wherey + hi(windmin) + 1, twidth, tlength - 2);
  1991.     for i := 1 to envcount do begin
  1992.         pause1;
  1993.         writeln(envstr(i))
  1994.     end
  1995. end;
  1996.  
  1997. (****************************************************************************)
  1998.  
  1999. procedure page_12;
  2000.  
  2001. const
  2002.     headermin = 0;
  2003.     headermax = 17;
  2004.     nuldev : string = 'NUL        ';
  2005.  
  2006. var
  2007.     FCB : array[$00..$24] of byte;
  2008.     header : array[headermin..headermax] of byte;
  2009.     i : byte;
  2010.     xword1 : word;
  2011.     xword2 : word;
  2012.  
  2013. begin
  2014.     caption1('Device      Units    Header       Attributes'
  2015.         + '             Strategy     Interrupt');
  2016.     writeln;
  2017.     window(1, wherey + hi(windmin), twidth, tlength - 2);
  2018.     case osminor of
  2019.         0..9 : begin
  2020.             fillchar(FCB, sizeof(FCB), 0);
  2021.             for i := 1 to 11 do
  2022.                 FCB[i] := ord(nuldev[i]);
  2023.             with regs do begin
  2024.                 AH := $0F;
  2025.                 DS := seg(FCB);
  2026.                 DX := ofs(FCB);
  2027.                 MSDOS(regs)
  2028.             end;
  2029.             xword1 := cbw(FCB[$1C], FCB[$1D]);
  2030.             xword2 := cbw(FCB[$1A], FCB[$1B])
  2031.         end;
  2032.         10..39 : begin
  2033.             xword1 := devseg;
  2034.             xword2 := devofs + $0022
  2035.         end
  2036.     end;
  2037.     while xword2 < $FFFF do begin
  2038.         pause1;
  2039.         for i := headermin to headermax do
  2040.             header[i] := mem[xword1 : xword2 + i];
  2041.         if header[5] and $80 = $00 then
  2042.             write('            ', header[10] : 5)
  2043.         else begin
  2044.             for i := 10 to headermax do
  2045.                 write(showchar(chr(header[i])));
  2046.             write('         ')
  2047.         end;
  2048.         write('    ');
  2049.         segofs1(xword1, xword2);
  2050.         write('    ', bin16(cbw(header[4], header[5])), '    ');
  2051.         segofs1(xword1, cbw(header[6], header[7]));
  2052.         write('    ');
  2053.         segofs2(xword1, cbw(header[8], header[9]));
  2054.         xword1 := cbw(header[2], header[3]);
  2055.         xword2 := cbw(header[0], header[1])
  2056.     end
  2057. end;
  2058.  
  2059. (****************************************************************************)
  2060.  
  2061. procedure page_13;
  2062.  
  2063. var
  2064.     i : $00..$2B;
  2065.     xbyte : byte;
  2066.     xchar : 'A'..'Z';
  2067.     xFCB : array[$00..$2B] of byte;
  2068.     xlong : longint;
  2069.     xstring : string;
  2070.     xword1 : word;
  2071.     xword2 : word;
  2072.     y : byte;
  2073.  
  2074. begin
  2075.     y := wherey + hi(windmin);
  2076.     window(1, y, twidth div 2, tlength - 2);
  2077.     if osminor >= 10 then begin
  2078.         caption2('LASTDRIVE');
  2079.         drvname(mem[devseg : devofs + $0021] - 1);
  2080.         writeln
  2081.     end;
  2082.     caption2('Diskette drives');
  2083.     if equip and $0001 = $0001 then
  2084.         writeln(1 + equip and $00C0 shr 6)
  2085.     else
  2086.         writeln(0);
  2087.     xword1 := longint(intvec[$1E]) shr 16;
  2088.     xword2 := longint(intvec[$1E]) and $0000FFFF;
  2089.     caption3('Sectors/track');
  2090.     writeln(mem[xword1 : xword2 + 4]);
  2091.     caption3('Bytes/sector');
  2092.     writeln(mem[xword1 : xword2 + 3] shl 8);
  2093.     caption3('On time (ms)');
  2094.     writeln(125 * mem[xword1 : xword2 + 10]);
  2095.     caption3('Off time (s)');
  2096.     writeln(longint(mem[xword1 : xword2 + 2]) shl 16 / tick1 : 0 : 1);
  2097.     caption3('Head settle time (ms)');
  2098.     writeln(mem[xword1 : xword2 + 9]);
  2099.     caption1('  Single drive is now ');
  2100.     xbyte := mem[BIOSdseg : $0104];
  2101.     if xbyte <= ord('Z') - ord('A') then begin
  2102.         drvname(xbyte);
  2103.         writeln
  2104.     end else if xbyte = $FF then
  2105.         writeln('N/A')
  2106.     else
  2107.         unknown('status', xbyte, 2);
  2108. (* Byte 12:12 p.178 *)
  2109.     writeln;
  2110.     caption1('Drive   Removable');
  2111.     if osminor >= 10 then begin
  2112.         caption1('   Remote');
  2113.         if osminor >= 20 then
  2114.             caption1('   Alias')
  2115.     end;
  2116.     writeln;
  2117.     window(wherex + lo(windmin), wherey + hi(windmin), twidth, tlength - 2);
  2118.     with regs do begin
  2119.         for xchar := 'A' to 'Z' do begin
  2120.             AH := $0E;
  2121.             DL := ord(xchar) - ord('A');
  2122.             MSDOS(regs);
  2123.             AH := $19;
  2124.             MSDOS(regs);
  2125.             if AL = DL then begin
  2126.                 pause1;
  2127.                 drvname(AL);
  2128.                 write('     ');
  2129.                 AX := $4408;
  2130.                 BL := 0;
  2131.                 MSDOS(regs);
  2132.                 if nocarry then
  2133.                     yesorno1(AL = $00)
  2134.                 else
  2135.                     write('?  ');
  2136.                 if osminor >= 10 then begin
  2137.                     write('         ');
  2138.                     AX := $4409;
  2139.                     BL := 0;
  2140.                     MSDOS(regs);
  2141.                     if nocarry then
  2142.                         yesorno1(DH and $10 = $10)
  2143.                     else
  2144.                         write('?  ');
  2145.                     if osminor >= 20 then begin
  2146.                         write('      ');
  2147.                         AX := $440E;
  2148.                         BL := 0;
  2149.                         MSDOS(regs);
  2150.                         if nocarry then
  2151.                             if AL = $00 then
  2152.                                 write('(none)')
  2153.                             else
  2154.                                 drvname(AL - 1)
  2155.                         else
  2156.                             write('?')
  2157.                     end
  2158.                 end;
  2159.                 writeln
  2160.             end
  2161.         end;
  2162.         AH := $0E;
  2163.         DL := currdrv;
  2164.         MSDOS(regs)
  2165.     end;
  2166.     window(1 + twidth div 2, y, twidth, tlength - 2);
  2167.     caption2('Current drive and path');
  2168.     getdir(0, xstring);
  2169.     writeln(xstring);
  2170.     caption3('Volume label');
  2171.     for i := $00 to $2B do
  2172.         xFCB[i] := $00;
  2173.     xFCB[$00] := $FF;                    (* extended FCB *)
  2174.     xFCB[$06] := $08;                    (* volume ID attribute *)
  2175.     for i := $08 to $12 do
  2176.         xFCB[i] := ord('?');
  2177.     with regs do begin
  2178.         AH := $11;
  2179.         DS := seg(xFCB);
  2180.         DX := ofs(xFCB);
  2181.         MSDOS(regs);
  2182.         case AL of
  2183.             $00 : begin
  2184.                 AH := $2F;
  2185.                 MSDOS(regs);
  2186.                 i := $08;
  2187.                 xchar := char(mem[ES : BX + i]);
  2188.                 while (i <= $12) and (xchar > #0) do begin
  2189.                     write(showchar(xchar));
  2190.                     inc(i);
  2191.                     xchar := char(mem[ES : BX + i])
  2192.                 end;
  2193.                 writeln
  2194.             end;
  2195.             $FF : writeln('(none)')
  2196.             else
  2197.                 unknown('status', AL, 2)
  2198.         end;
  2199.         AH := $1B;
  2200.         MSDOS(regs);
  2201.         media(mem[DS : BX]);
  2202.         caption3('Clusters');
  2203.         writeln(DX);
  2204.         caption3('Sectors/cluster');
  2205.         writeln(AL);
  2206.         caption3('Bytes/sector');
  2207.         writeln(CX)
  2208.     end;
  2209.     caption3('Total space (bytes)');
  2210.     xlong := disksize(0);
  2211.     if xlong <> -1 then
  2212.         writeln(xlong : 8)
  2213.     else
  2214.         dontknow2;
  2215.     caption3('Free space (bytes) ');
  2216.     xlong := diskfree(0);
  2217.     if xlong <> -1 then
  2218.         writeln(xlong : 8)
  2219.     else
  2220.         dontknow2
  2221. end;
  2222.  
  2223. (****************************************************************************)
  2224.  
  2225. procedure page_14;
  2226.  
  2227. var
  2228.     i : byte;
  2229.     xbool : boolean;
  2230.     xbyte1 : byte;
  2231.     xbyte2 : byte;
  2232.     y : byte;
  2233.  
  2234. begin
  2235.     caption2('BIOS disk parameters');
  2236.     xbool := true;
  2237.     for i := $00 to $FF do
  2238.         with regs do begin
  2239.             AH := $08;
  2240.             DL := i;
  2241.             intr($13, regs);
  2242.             if nocarry and ((BL > $00) or (i >= $80)) then
  2243.                 begin
  2244.                 if xbool then begin
  2245.                     xbool := false;
  2246.                     writeln;
  2247.                     y := wherey + hi(windmin);
  2248.                     caption3('Unit');
  2249.                     writeln;
  2250.                     caption3('Type');
  2251.                     writeln;
  2252.                     caption3('Drives');
  2253.                     writeln;
  2254.                     caption3('Heads');
  2255.                     writeln;
  2256.                     caption3('Cylinders');
  2257.                     writeln;
  2258.                     caption3('Sectors/track');
  2259.                     writeln;
  2260.                     caption3('Specify bytes');
  2261.                     writeln;
  2262.                     caption3('Off time (s)');
  2263.                     writeln;
  2264.                     caption3('Bytes/sector');
  2265.                     writeln;
  2266.                     caption3('Sectors/track');
  2267.                     writeln;
  2268.                     caption3('Gap length');
  2269.                     writeln;
  2270.                     caption3('Data length');
  2271.                     writeln;
  2272.                     caption3('Gap length for format');
  2273.                     writeln;
  2274.                     caption3('Fill byte for format');
  2275.                     writeln;
  2276.                     caption3('Head settle time (ms)');
  2277.                     writeln;
  2278.                     caption3('On time (ms)');
  2279.                     writeln;
  2280.                     xbyte1 := 27
  2281.                 end;
  2282.                 if xbyte1 + 10 > twidth then begin
  2283.                     pause2;
  2284.                     xbyte1 := 27;
  2285.                     window(xbyte1, y, twidth, tlength - 2);
  2286.                     clrscr
  2287.                 end;
  2288.                 window(xbyte1, y, xbyte1 + 11, tlength - 2);
  2289.                 writeln(i);
  2290.                 if i < $80 then
  2291.                     case BL of
  2292.                         $01 : writeln('360KB 5¼"');
  2293.                         $02 : writeln('1.2MB 5¼"');
  2294.                         $03 : writeln('720KB 3½"');
  2295.                         $04 : writeln('1.44MB 3½"')
  2296.                         else
  2297.                             writeln('(', hex(BL, 2), ')')
  2298.                     end
  2299.                 else
  2300.                     writeln('fixed disk');
  2301.                 writeln(DL);
  2302.                 writeln(DH + 1);
  2303.                 writeln(cbw(CH, CL shr 6) + 1);
  2304.                 writeln(CL and $3F);
  2305.                 if i < $80 then begin
  2306.                     writeln('$', hex(mem[ES : DI], 2), ' $'
  2307.                         , hex(mem[ES : DI + $0001], 2));
  2308.                     writeln(longint(mem[ES : DI + $0002]) shl 16 / tick1 : 0
  2309.                         : 1);
  2310.                     xbyte2 := mem[ES : DI + $0003];
  2311.                     case xbyte2 of
  2312.                         $00 : writeln('128');
  2313.                         $01 : writeln('256');
  2314.                         $02 : writeln('512');
  2315.                         $03 : writeln('1024')
  2316.                         else
  2317.                             writeln('(', hex(xbyte2, 4), ')')
  2318.                     end;
  2319.                     writeln(mem[ES : DI + $0004]);
  2320.                     writeln(mem[ES : DI + $0005]);
  2321.                     writeln(mem[ES : DI + $0006]);
  2322.                     writeln(mem[ES : DI + $0007]);
  2323.                     writeln('$', hex(mem[ES : DI + $0008], 2));
  2324.                     writeln(mem[ES : DI + $0009]);
  2325.                     writeln(125 * mem[ES : DI + $000A])
  2326.                 end;
  2327.                 inc(xbyte1, 13)
  2328.             end
  2329.         end;
  2330.     if xbool then
  2331.         writeln('(no disks)')
  2332. end;
  2333.  
  2334. (****************************************************************************)
  2335.  
  2336. procedure page_15;
  2337.  
  2338. var
  2339.     i : byte;
  2340.     j : 0..3;
  2341.     k : byte;
  2342.     part : array[$00..secsiz - 1] of byte;
  2343.     xbool1 : boolean;
  2344.     xbool2 : boolean;
  2345.     xbyte1 : byte;
  2346.     xbyte2 : byte;
  2347.     xlong : longint;
  2348.     xword : word;
  2349.     y : byte;
  2350.  
  2351. function getpart(a : byte) : boolean;
  2352.  
  2353. var
  2354.     parmblk : array[$00..$25] of byte;
  2355.  
  2356. begin
  2357.     with regs do begin
  2358.         AX := $440D;
  2359.         BL := a;
  2360.         CX := $0860;
  2361.         DS := seg(parmblk);
  2362.         DX := ofs(parmblk);
  2363.         parmblk[$00] := $04;
  2364.         MSDOS(regs);
  2365.         if nocarry and (parmblk[$01] = 5) then begin
  2366.             AX := $440D;
  2367.             BL := a;
  2368.             CX := $0861;
  2369.             DS := seg(parmblk);
  2370.             DX := ofs(parmblk);
  2371.             fillchar(parmblk, sizeof(parmblk), $00);
  2372.             parmblk[$00] := $04;
  2373.             parmblk[$08] := $01;
  2374.             parmblk[$09] := lo(ofs(part));
  2375.             parmblk[$0A] := hi(ofs(part));
  2376.             parmblk[$0B] := lo(seg(part));
  2377.             parmblk[$0C] := hi(seg(part));
  2378.             MSDOS(regs);
  2379.             getpart := nocarry
  2380.         end else
  2381.             getpart := false
  2382.     end
  2383. end;
  2384.  
  2385. begin (* procedure page_15 *)
  2386.     caption2('Partition tables');
  2387.     if osminor >= 20 then begin
  2388.         i := 1;
  2389.         xbool1 := false;
  2390.         repeat
  2391.             if getpart(i) then
  2392.                 xbool1 := true
  2393.             else
  2394.                 inc(i)
  2395.         until xbool1 or (i > 26);
  2396.         if xbool1 then begin
  2397.             writeln;
  2398.             y := wherey + hi(windmin);
  2399.             caption3('Drive');
  2400.             writeln;
  2401.             caption3('Partition');
  2402.             writeln;
  2403.             caption3('Type');
  2404.             writeln;
  2405.             caption3('Bootable');
  2406.             writeln;
  2407.             caption3('Starting cylinder');
  2408.             writeln;
  2409.             caption3('Starting head');
  2410.             writeln;
  2411.             caption3('Starting sector');
  2412.             writeln;
  2413.             caption3('Ending cylinder');
  2414.             writeln;
  2415.             caption3('Ending head');
  2416.             writeln;
  2417.             caption3('Ending sector');
  2418.             writeln;
  2419.             caption3('First partition sector');
  2420.             writeln;
  2421.             caption3('Sectors in partition');
  2422.             writeln;
  2423.             repeat
  2424.                 window(10, y, twidth, tlength - 2);
  2425.                 drvname(i - 1);
  2426.                 window(27, y + 1, twidth, tlength - 2);
  2427.                 clrscr;
  2428.                 for j := 0 to 3 do begin
  2429.                     window(27 + 14 * j, y + 1, 38 + 14 * j, tlength - 2);
  2430.                     writeln(j + 1);
  2431.                     xword := $01BE + j shl 4;
  2432.                     xbyte1 := part[xword + 4];
  2433.                     case xbyte1 of
  2434.                         $00 : writeln('not used');
  2435.                         $01 : writeln('DOS-12');
  2436.                         $04 : writeln('DOS-16');
  2437.                         $05 : writeln('Ext DOS');
  2438.                         $06 : writeln('"Huge" DOS')
  2439.                         else
  2440.                             writeln('(', hex(xbyte1, 2), ')')
  2441.                     end;
  2442.                     if xbyte1 > $00 then begin
  2443.                         xbyte2 := part[xword];
  2444.                         case xbyte2 of
  2445.                             $00 : writeln('no');
  2446.                             $80 : writeln('yes')
  2447.                             else
  2448.                                 writeln('(', hex(xbyte2, 2), ')')
  2449.                         end;
  2450.                         writeln(cbw(part[xword + 3], part[xword + 2] shr 6));
  2451.                         writeln(part[xword + 1]);
  2452.                         writeln(part[xword + 2] and $3F);
  2453.                         writeln(cbw(part[xword + 7], part[xword + 6] shr 6));
  2454.                         writeln(part[xword + 5]);
  2455.                         writeln(part[xword + 6] and $3F);
  2456.                         xlong := 0;
  2457.                         for k := 11 downto 8 do
  2458.                             xlong := xlong shl 8 + part[xword + k];
  2459.                         writeln(xlong);
  2460.                         xlong := 0;
  2461.                         for k := 15 downto 12 do
  2462.                             xlong := xlong shl 8 + part[xword + k];
  2463.                         writeln(xlong)
  2464.                     end else
  2465.                         for k := 2 to 10 do
  2466.                             writeln('-')
  2467.                 end;
  2468.                 repeat
  2469.                     inc(i);
  2470.                     xbool2 := getpart(i)
  2471.                 until xbool2 or (i > 26);
  2472.                 if xbool2 then
  2473.                     pause2
  2474.             until i > 26
  2475.         end else
  2476.             writeln('(no fixed disks)')
  2477.     end else
  2478.         writeln('(not available under this DOS version)')
  2479. end;
  2480.  
  2481. (****************************************************************************)
  2482.  
  2483. procedure page_16;
  2484.  
  2485. var
  2486.     bootrec : array[0..secsiz - 1] of byte;
  2487.     i : 1..26;
  2488.     j : word;
  2489.     xbool : boolean;
  2490.     xbyte : byte;
  2491.     xchar : char;
  2492.     xword1 : word;
  2493.     xword2 : word;
  2494.     xword3 : word;
  2495.     xword4 : word;
  2496.     xword5 : word;
  2497.     y : byte;
  2498.  
  2499. begin
  2500.     y := wherey + hi(windmin);
  2501.     window(1, y, twidth div 2, tlength - 2);
  2502.     caption1('Boot record');
  2503.     writeln;
  2504.     xword1 := diskread(currdrv, 0, 1, bootrec);
  2505.     if xword1 = $0000 then begin
  2506.         caption3('Drive');
  2507.         drvname(currdrv);
  2508.         writeln;
  2509.         media(bootrec[$15]);
  2510.         caption3('Sectors/cluster');
  2511.         writeln(bootrec[$0D]);
  2512.         caption3('Bytes/sector');
  2513.         writeln(cbw(bootrec[$0B], bootrec[$0C]));
  2514.         caption3('Reserved sectors');
  2515.         writeln(cbw(bootrec[$0E], bootrec[$0F]));
  2516.         caption3('FAT''s');
  2517.         writeln(bootrec[$10]);
  2518.         caption3('Sectors/FAT');
  2519.         writeln(cbw(bootrec[$16], bootrec[$17]));
  2520.         caption3('Root directory entries');
  2521.         writeln(cbw(bootrec[$11], bootrec[$12]));
  2522.         writeln;
  2523.         caption3('Heads');
  2524.         writeln(cbw(bootrec[$1A], bootrec[$1B]));
  2525.         caption3('Total sectors');
  2526.         writeln(cbw(bootrec[$13], bootrec[$14]));
  2527.         caption3('Sectors/track');
  2528.         writeln(cbw(bootrec[$18], bootrec[$17]));
  2529.         caption3('Hidden sectors');
  2530.         writeln(cbw(bootrec[$1C], bootrec[$1D]));
  2531.         caption3('OEM name and version');
  2532.         for i := $03 to $0A do
  2533.             write(showchar(chr(bootrec[i])));
  2534.         writeln
  2535.     end else begin
  2536.         writeln('  Can''t read boot record');
  2537.         write('  ');
  2538.         xbyte := hi(xword1);
  2539.         case xbyte of
  2540.             $80 : writeln('Attachment failed to respond');
  2541.             $40 : writeln('Seek operation failed');
  2542.             $20 : writeln('Controller failed');
  2543.             $10 : writeln('Data error (bad CRC)');
  2544.             $08 : writeln('DMA failure');
  2545.             $04 : writeln('Sector not found');
  2546.             $03 : writeln('Write-protect fault');
  2547.             $02 : writeln('Bad address mark');
  2548.             $01 : writeln('Bad command');
  2549.             $00 : writeln
  2550.             else
  2551.                 unknown('error', xbyte, 2)
  2552.         end;
  2553.         write('  ');
  2554.         xbyte := lo(xword1);
  2555.         case xbyte of
  2556.             $00 : writeln('Write-protect error');
  2557.             $01 : writeln('Unknown unit');
  2558.             $02 : writeln('Drive not ready');
  2559.             $03 : writeln('Unknown command');
  2560.             $04 : writeln('Data error (bad CRC)');
  2561.             $05 : writeln('Bad request structure length');
  2562.             $06 : writeln('Seek error');
  2563.             $07 : writeln('Unknown media type');
  2564.             $08 : writeln('Sector not found');
  2565.             $09 : writeln('Printer out of paper');
  2566.             $0A : writeln('Write fault');
  2567.             $0B : writeln('Read fault');
  2568.             $0C : writeln('General failure')
  2569.             else
  2570.                 unknown('error', xbyte, 2)
  2571.         end
  2572.     end;
  2573.     window(1 + twidth div 2, y, twidth, tlength - 2);
  2574.     caption1('DOS disk parameters');
  2575.     writeln;
  2576.     if osminor >= 10 then begin
  2577.         i := 1;
  2578.         xbool := false;
  2579.         xword1 := memw[devseg : devofs + $0018];
  2580.         xword2 := memw[devseg : devofs + $0016];
  2581.         repeat
  2582.             window(1 + twidth div 2, y + 1, twidth, tlength - 2);
  2583.             caption3('Drive');
  2584.             drvname(i - 1);
  2585.             writeln;
  2586.             xword3 := memw[xword1 : xword2 + $0047];
  2587.             xword4 := memw[xword1 : xword2 + $0045];
  2588.             media(mem[xword3 : xword4 + $0016]);
  2589.             caption3('Sectors/cluster');
  2590.             writeln(mem[xword3 : xword4 + $0004] + 1);
  2591.             caption3('Bytes/sector');
  2592.             writeln(memw[xword3 : xword4 + $0002]);
  2593.             caption3('Reserved sectors');
  2594.             writeln(memw[xword3 : xword4 + $0006]);
  2595.             caption3('FAT''s');
  2596.             writeln(mem[xword3 : xword4 + $0008]);
  2597.             caption3('Sectors/FAT');
  2598.             writeln(mem[xword3 : xword4 + $000F]);
  2599.             caption3('Root directory entries');
  2600.             writeln(memw[xword3 : xword4 + $0009]);
  2601.             writeln;
  2602.             caption3('DPB valid');
  2603.             yesorno2(mem[xword3 : xword4 + $0017] < $FF);
  2604.             caption3('Current directory');
  2605.             j := xword2;
  2606.             xchar := chr(mem[xword1 : j]);
  2607.             while xchar > #0 do begin
  2608.                 write(xchar);
  2609.                 inc(j);
  2610.                 xchar := chr(mem[xword1 : j])
  2611.             end;
  2612.             writeln;
  2613.             caption3('Device header');
  2614.             segofs2(memw[xword3 : xword4 + $0014]
  2615.                 , memw[xword3 : xword4 + $0012]);
  2616.             caption3('Unit within driver');
  2617.             writeln(mem[xword3 : xword4 + $0001]);
  2618.             caption3('Clusters');
  2619.             writeln(memw[xword3 : xword4 + $000D] - 1);
  2620.             caption3('Cluster to sector shift');
  2621.             writeln(mem[xword3 : xword4 + $0005]);
  2622.             caption3('Root directory sector');
  2623.             writeln(memw[xword3 : xword4 + $0010]);
  2624.             caption3('First data sector');
  2625.             writeln(memw[xword3 : xword4 + $000B]);
  2626.             caption3('Next DPB');
  2627.             xword5 := memw[xword3 : xword4 + $0018];
  2628.             segofs2(memw[xword3 : xword4 + $001A], xword5);
  2629.             if xword5 < $FFFF then begin
  2630.                 write('  ');
  2631.                 pause2;
  2632.                 clrscr;
  2633.                 inc(i);
  2634.                 inc(xword2, $51)
  2635.             end else
  2636.                 xbool := true
  2637.         until xbool
  2638.     end else
  2639.         writeln('(not available under this DOS version)')
  2640. end;
  2641.